/**
 * Author(s): xuming.Wong <xuming.Wong@gmail.com>
 */

#ifndef __QS_Transaction_H__
#define __QS_Transaction_H__

#include "Prerequisites.h"
#include "Utilities.h"

namespace QSThink
{

	class TransactionSingle;
	class Transaction2Minutes;
	class Transaction1Day;


	class Transaction
	{
	public:
		enum Type{
			Transaction_Single,
			Transaction_2Minutes,
			Transaction_5Minutes,
			Transaction_30Minutes,
			Transaction_1Hour,
			Transaction_1Day,

			Transaction_Type_Count
		};

		virtual Transaction::Type getType()=0;
		
		

	};
	
	/*Every single transaction data 
	*/
	class TransactionSingle : public Transaction
	{
	public:
		TransactionSingle();
		TransactionSingle(int time,int price,int volume,int amount,int flag);

		Transaction::Type getType(){
			return Transaction_Single;
		}

		int flag;//now 0 means buy ,1 means sold, 2 mean middle
		int time;//seconds passed from 9:00 for CN
		int price;//price already multiply 100

		//can be produced by amount/price//this feild is just for validation
		int volume;//already divided by 100//already divided by 100 not accuracy

		int amount;//in yuan(RMB)
	};

	class Transaction2Minutes : public Transaction
	{
	public:
		
		Transaction2Minutes()
		{
			_index=0;
			_volume=0;
			_amount=0;
		}

		Transaction::Type getType(){
			return Transaction_2Minutes;
		}

		void addTrans(TransactionSingle* trans){
			_transactions.push_back(trans);

			_amount+=trans->amount;
			//_volume+=trans->volume;//multiplied by 100
			_volume+=(float)trans->amount/(float)trans->price;//this is more 

		}

		float balancePrice(){
			return (float)_amount/(float)_volume;
		}

		int index(){
			return _index;
		}

		void setIndex(int index){
			_index=index;
		}

	protected:
		std::vector<TransactionSingle*> _transactions;

		int _index;//2 minutes index
		float _volume;//
		float _amount;//in yuan(RMB)

	};

	class TransactionDatabase;
	class Transaction1Day  : public Transaction
	{
	public:
		Transaction1Day(QString symbol,int day);

		Transaction::Type getType(){
			return Transaction_1Day;
		}

		//return false if data is not valid.
		bool fillData(QByteArray bytes);

		bool valid(){
			return _valid;
		}

		bool loadData();
		
		bool hasData(){
			return _transactions.size()>0;
		}
		
		bool statisticed(){
			return _statisticed||hasData();//data can induce metadata
		}

		int day()
		{
			return _day;
		}

		int getTransCount(){
			return _transactions.size();
		}

		int get2MinutesCount(){
			return 120;//
		}

		int highPrice(){
			return _highPrice;
		}

		int highIndex(){
			return _highIndex;
		}

		int lowPrice(){
			return _lowPrice;
		}

		int lowIndex(){
			return _lowIndex;
		}

		int openPrice(){
			return _openPrice;
		}

		int closePrice(){
			return _closePrice;
		}

		float balancePrice(){
			return _balancePrice;
		}

		float balancePriceEx();

		float lowPriceEx();
		float highPriceEx();

		int volume(){
			return _volume;
		}

		int amount(){
			return _amount;
		}

		TransactionSingle* getTransaction(int index){
			return _transactions[index];

		}

		Transaction2Minutes* get2MinutesTransaction(int index){
			return _2minutesTrans+index;

		}


		QString symbol(){
			return _symbol;
		}

		QDate date(){
			return Utilities::getDateByDay(_day);
		}

		TransactionSingle* parseLine(QString line );
		bool initTransactionsByText( QByteArray bytes );
		void persit();
		void calcDayInfo();
		void calc2MinutesTrans();
	protected:
		friend class StockTransactions;
		void setStatistics( float balancePrice, int openPrice, int closePrice, int highPrice, int highIndex, int lowPrice, int lowIndex, int volume, int amount );
	protected:
		QString _symbol;//which stock
		int _day;//which day

		bool _valid;//data is right?
		bool _statisticed;//this day have a small snapshot?



		//Need calculated by transactions
		float _balancePrice;//all price/all count of trans
		int _openPrice;//first transaction//not so important in this soft
		int _closePrice;//last transaction
		int _highPrice;//highest price of the day.*100
		int _highIndex;//highest price transaction index
		int _lowPrice;//lowest price of the day.//calculated by all transactions
		int _lowIndex;//lowest price's transaction index
		int _volume;//all day volume
		int _amount;//all day money

		


		//real data
		std::vector<TransactionSingle*> _transactions;

		Transaction2Minutes _2minutesTrans[120];//4 working hour=4*60 minutes=120*2minutes


		//Transaction5Minutes
		//Transaction30Minutes
		//Transaction1Hour

	};


	


}

#endif
